// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#include "mk_header.h"
#include "mk_particle_modifier_color.h"

namespace MK3DE
{
	DWORD CParticleModifierColor::__Interpolate(DWORD a1, DWORD r1, DWORD g1, DWORD b1, DWORD a2, DWORD r2, DWORD g2, DWORD b2, float factor)
	{
		float inv = 1.0f - factor;
		DWORD a = (DWORD)(a1 * factor + a2 * inv);
		DWORD r = (DWORD)(r1 * factor + r2 * inv);
		DWORD g = (DWORD)(g1 * factor + g2 * inv);
		DWORD b = (DWORD)(b1 * factor + b2 * inv);
		return D3DCOLOR_ARGB(a, r, g, b);
	}

	void CParticleModifierColor::Apply(Particle* particle, DWORD dt)
	{
		GetValue(particle->Life, particle->Color);
	}

	BOOL CParticleModifierColor::GetValue(DWORD dwLife, DWORD& data)
	{
		if (_vecKeyFrame.size() == 0)
			return FALSE;

		std::vector<__KeyFrame>::iterator i = _vecKeyFrame.begin();
		while (i != _vecKeyFrame.end())
		{
			__KeyFrame& keyFrame = *i;
			if (keyFrame.Life < dwLife)
			{
				if (i == _vecKeyFrame.begin())
				{
					data = MK_COLOR_ARGB(keyFrame.a, keyFrame.r, keyFrame.g, keyFrame.b);
					return TRUE;
				}
				else
				{
					__KeyFrame& keyFrame2 = *(i - 1);
					data = __Interpolate(
						keyFrame2.a, keyFrame2.r, keyFrame2.g, keyFrame2.b, 
						keyFrame.a, keyFrame.r, keyFrame.g, keyFrame.b, 
						(float)(dwLife - keyFrame.Life) / (keyFrame2.Life - keyFrame.Life));

					return TRUE;
				}
			}

			++i;
		}

		__KeyFrame& keyFrame = *(i - 1);
		data = MK_COLOR_ARGB(keyFrame.a, keyFrame.r, keyFrame.g, keyFrame.b); 
		return TRUE;
	}

	BOOL CParticleModifierColor::SetKeyFrame(DWORD dwLife, DWORD data)
	{
		std::vector<__KeyFrame>::iterator i = _vecKeyFrame.begin();
		while (i != _vecKeyFrame.end())
		{
			__KeyFrame& keyFrame = *i;
			if (dwLife == keyFrame.Life)
			{
				keyFrame.Life = dwLife;
				keyFrame.a = MK_COLOR_GETA(data);
				keyFrame.r = MK_COLOR_GETR(data);
				keyFrame.g = MK_COLOR_GETG(data);
				keyFrame.b = MK_COLOR_GETB(data);

				return TRUE;
			}
			else if (dwLife > keyFrame.Life)
				break;

			++i;
		}

		__KeyFrame keyFrame;
		keyFrame.Life = dwLife;
		keyFrame.a = MK_COLOR_GETA(data);
		keyFrame.r = MK_COLOR_GETR(data);
		keyFrame.g = MK_COLOR_GETG(data);
		keyFrame.b = MK_COLOR_GETB(data);

		_vecKeyFrame.insert(i, keyFrame);
		return TRUE;
	}

	BOOL CParticleModifierColor::GetKeyFrame(DWORD dwLife, /* out */ DWORD& data)
	{
		std::vector<__KeyFrame>::iterator i = _vecKeyFrame.begin();
		while (i != _vecKeyFrame.end())
		{
			__KeyFrame& keyFrame = *i;
			if (dwLife == keyFrame.Life)
			{
				data = MK_COLOR_ARGB(keyFrame.a, keyFrame.r, keyFrame.g, keyFrame.b);
				return TRUE;
			}

			++i;
		}

		return FALSE;
	}

	BOOL CParticleModifierColor::GetKeyFrameByIndex(DWORD index, /* out */ DWORD& dwLife, /* out */ DWORD& data)
	{
		if (index >= _vecKeyFrame.size())
			return FALSE;

		__KeyFrame& keyFrame = *(_vecKeyFrame.begin() + index);
		dwLife = keyFrame.Life;
		data = MK_COLOR_ARGB(keyFrame.a, keyFrame.r, keyFrame.g, keyFrame.b);
		return TRUE;
	}

	BOOL CParticleModifierColor::RemoveKeyFrame(DWORD index)
	{
		if (index >= _vecKeyFrame.size())
			return FALSE;

		_vecKeyFrame.erase(_vecKeyFrame.begin() + index);
		return TRUE;
	}
}